package mo_gorm

import (
	"MoSkeleton/framework/core/config/properties_db"
	"MoSkeleton/framework/core/moerrors"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"gorm.io/gorm/schema"
	"log"
	"os"
	"time"
)

type MoDbBase interface {
	GenDb(dbConfig *properties_db.GeneralDB, testConn bool) (db gorm.DB, err error)
}

func GenDbByPersistentDb(dbConfig *properties_db.PersistentDb, testConn bool) (db *gorm.DB, err error) {
	db, err = createDbByPersistentDb(dbConfig, testConn)
	if err != nil {
		return nil, err
	}
	if db != nil {
		err = initDB(db)
		if err != nil {
			return nil, err
		}
		err = initDbCallback(db)
		if err != nil {
			return nil, err
		}
	}
	return
}

func initDbCallback(db *gorm.DB) error {
	err := db.Callback().Create().Before("gorm:before_create").Register("mo:before_create:snowflakeId", DoFillModelSnowflakeIdBeforeCreate)
	if err != nil {
		//MoLogger.Error("init db callback error", zap.Error(err))
		return err
	}
	return nil
}
func initDB(db *gorm.DB) error {
	return nil
}
func createDbByPersistentDb(dbConfig *properties_db.PersistentDb, testConn bool) (*gorm.DB, error) {
	switch dbConfig.DbType {
	case "mysql":
		mysqlDb := &MoMysqlDb{}
		var dbProvider properties_db.GeneralDBProvider = &dbConfig.Mysql
		return mysqlDb.GenDb(&dbProvider, testConn)
	case "mssql":
		mssqlDb := &MoMssqlDb{}
		var dbProvider properties_db.GeneralDBProvider = &dbConfig.Mssql
		return mssqlDb.GenDb(&dbProvider, testConn)
	case "oracle":
		oracleDb := &MoOracleDb{}
		var dbProvider properties_db.GeneralDBProvider = &dbConfig.Oracle
		return oracleDb.GenDb(&dbProvider, testConn)
	case "pgsql":
		pgsqlDb := &MoPgsqlDb{}
		var dbProvider properties_db.GeneralDBProvider = &dbConfig.Pgsql
		return pgsqlDb.GenDb(&dbProvider, testConn)
	case "sqlite":
		sqliteDb := &MoSqliteDb{}
		var dbProvider properties_db.GeneralDBProvider = &dbConfig.Sqlite
		return sqliteDb.GenDb(&dbProvider, testConn)
	default:
		return nil, moerrors.NewWithMsg("dbType is not support")
	}
}

func gormConfig(general *properties_db.GeneralDB, prefix string, singular bool) *gorm.Config {

	return &gorm.Config{
		Logger: logger.New(NewWriter(*general, log.New(os.Stdout, "\r\n", log.LstdFlags)), logger.Config{
			SlowThreshold: 200 * time.Millisecond,
			LogLevel:      general.LogLevel(),
			Colorful:      true,
		}),
		NamingStrategy: schema.NamingStrategy{
			TablePrefix:   prefix,
			SingularTable: singular,
		},
		DisableForeignKeyConstraintWhenMigrating: true,
	}
}
